﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.Reporting.WebForms;
using System.Drawing;
using System.IO;
using System.Data;
using System.Drawing.Imaging;

namespace AcadPosApp.Boletos
{
    public partial class boletoBanese : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                if (Session["dadosParcelas"] != null)
                {
                    DataTable dtDadosBoleto = (DataTable)Session["dadosParcelas"];
                    string tipo = Session["tipoBoleto"].ToString();
                    gerarBoleto(dtDadosBoleto, tipo);
                }
            }
        }

        private void gerarBoleto(DataTable dadoBoleto, string pTipoBoleto)
        {
            ViewState["Inst1"] = string.Empty;
            ViewState["Inst2"] = string.Empty;
            ViewState["Inst3"] = string.Empty;
            ViewState["NossoNumeros"] = new string[12];
            ViewState["Codigo"] = new string[44];
            ViewState["CodFV"] = new string[12];
            ViewState["CDAsBace"] = new string[25];
            ViewState["Digito1"] = new string[1];
            ViewState["Digito2"] = new string[1];

            ReportViewer rvrRelatorio = new ReportViewer();
            rvrRelatorio.Reset();
            rvrRelatorio.ProcessingMode = ProcessingMode.Local;
            rvrRelatorio.LocalReport.ReportPath = Server.MapPath(@"boletoBanese.rdlc");
            rvrRelatorio.LocalReport.DataSources.Clear();

            ReportParameter rp_Informacao = new ReportParameter("rp_Informacao", Session["InformacoesBoleto"].ToString());
            ReportParameter[] ReportParans = new ReportParameter[] { rp_Informacao };
            rvrRelatorio.LocalReport.SetParameters(ReportParans);

            ReportDataSource rds = new ReportDataSource();
            rds.Name = "DataSetBoleto";

            DataTable dt = dadoBoleto;
            if (dt.Rows.Count > 0)
            {
                dt.Columns.Add("LINHA_DIGITAVEL");
                dt.Columns.Add("ASBACE");
                dt.Columns.Add("CODIGO_BARRA", typeof(Byte[]));
                dt.Columns.Add("VENCIMENTO");

                string getCodigoBarra = string.Empty;
                Bitmap barra = null;
                MemoryStream ms = new MemoryStream();
                string retorno = string.Empty;
                string CodigoBarras = string.Empty;
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    NossoNumero(dt.Rows[i]["NOSSO_NUMERO"].ToString());
                    dt.Rows[i]["ASBACE"] = ASBace();
                    CodigoBarras = CodBarra(Convert.ToDouble(dt.Rows[i]["VALOR_AJUSTADO"]), Convert.ToDateTime(dt.Rows[i]["DATA_VENCIMENTO"].ToString()));
                    barra = CodigoBarra(CodigoBarras);
                    barra.Save(ms, ImageFormat.Bmp);
                    byte[] bitmapData = ms.ToArray();
                    dt.Rows[i]["CODIGO_BARRA"] = bitmapData;
                    dt.Rows[i]["LINHA_DIGITAVEL"] = LinhaDigitavel();
                    dt.Rows[i]["VENCIMENTO"] = dt.Rows[i]["DATA_VENCIMENTO"];
                }

                rds.Value = dt;
                rvrRelatorio.LocalReport.DataSources.Add(rds);

                Warning[] warn = null;
                string[] streamids = null;
                string mimeType = "application/pdf";
                string encoding = string.Empty;
                string extension = string.Empty;
                byte[] byteViewer;

                byteViewer = rvrRelatorio.LocalReport.Render("Pdf", null, out mimeType, out encoding, out extension, out streamids, out warn);
                Response.Buffer = true;
                Response.Clear();
                Response.ContentType = "application/pdf";
                Response.AddHeader("content-disposition", "inline; filename=boletoBanese.pdf");
                Response.BinaryWrite(byteViewer);
                Response.Flush();
                Response.End();
            }
            else
            {
                ScriptManager.RegisterStartupScript(Page, Page.GetType(), "Alert", string.Format("alert('{0}');", "Não foram localizadas parcelas à serem impressas!"), true);
            }
            Session["dadosParcelas"] = null;
            Session["tipoBoleto"] = null;
        }

        #region Fator Vencimento
        public string CalculaFatorVencimento(DateTime DataDesejada)
        {
            string sFatorVencto;
            TimeSpan lTimeSpan = DataDesejada.Subtract(new DateTime(1997, 10, 7));
            sFatorVencto = lTimeSpan.Days.ToString();
            sFatorVencto = sFatorVencto.PadLeft(4, '0');
            if (sFatorVencto.StartsWith("0")) return "0000";
            else return sFatorVencto;
        }
        #endregion

        #region Modulo 10
        public string Modulo10(string Valor)
        {
            int nSoma = 0, nMult = 2, nIndice, nProd;

            for (nIndice = Valor.Length - 1; nIndice >= 0; nIndice--)
            {
                nProd = (Convert.ToByte(Valor[nIndice]) - 48) * nMult;

                if (nProd > 9) nSoma += nProd - 9;
                else nSoma += nProd;

                if (nMult == 2) nMult = 1;
                else nMult = 2;
            }

            nSoma = nSoma % 10;
            if (nSoma > 0) nSoma = 10 - nSoma;
            return nSoma.ToString();
        }
        #endregion

        #region * Início do Módulo 11
        /// <summary>
        ///Esse é o Modulo 11 responsável pelo Nosso Número 
        /// </summary>
        /// <param name="Valor">Valor a ser inserido para retorno do DV</param>
        /// <param name="Base">Base que pode variar de 2 a 9 </param>
        /// <returns></returns>
        private string Modulo11(string Valor, int Base, bool Resto)
        {
            int Contador, Peso, Digito, Soma;
            Soma = 0;
            Peso = 2;
            string retorno = string.Empty;

            for (Contador = Valor.Length - 1; Contador >= 0; Contador--)
            {
                Soma = Soma + (int.Parse(Valor[Contador].ToString()) * Peso);
                //Soma = Soma + (Convert.ToInt32(Valor.Substring(Contador, 1)) * Peso);
                if (Peso < Base)
                {
                    Peso = Peso + 1;
                }
                else
                {
                    Peso = 2;
                }
            }
            if (Resto)
                retorno = (Soma % 11).ToString();
            else
            {
                Digito = 11 - (Soma % 11);
                if (Digito > 9)
                    Digito = 0;
                retorno = Digito.ToString();
            }
            return retorno;
        }
        #endregion ( Fim do Módulo 11 )

        #region Modulo 11 Linha
        public string Modulo11Linha(string Valor, int Base, bool Resto)
        {
            int Soma, Rest, Contador, Peso, Digito;
            Soma = 0;
            Peso = 2;
            string retorno = string.Empty;

            for (Contador = Valor.Length - 1; Contador >= 0; Contador--)
            {
                Soma = Soma + (int.Parse(Valor[Contador].ToString()) * Peso);
                if (Peso < Base)
                    Peso = Peso + 1;
                else
                    Peso = 2;
            }

            if (Resto)
            {
                Rest = (Soma % 11);
                if (Rest >= 2)
                {
                    retorno = (11 - Rest).ToString();
                }
                else
                {
                    retorno = "1";
                }
            }
            return retorno;
        }

        #endregion

        #region Modulo 11 ASBACE
        public void Modulo11ASBACE(string Valor, int Base, bool Resto)
        {
            int Soma, Rest, Contador, Peso, Digito;
            Soma = 0;
            Peso = 2;
            Rest = 0;

            for (Contador = Valor.Length - 1; Contador >= 0; Contador--)
            {
                Soma = Soma + (Convert.ToInt32(Valor.Substring(Contador, 1)) * Peso);
                if (Peso < Base)
                {
                    Peso = Peso + 1;
                }
                else
                {
                    Peso = 2;
                }
            }
            Rest = (Soma % 11);
            if (Rest == 0)
            {
                ViewState["Digito2"] = "0";
            }
            else
                if (Rest == 1)
                {
                    if (Convert.ToInt32(ViewState["Digito1"]) < 9)
                    {
                        ViewState["Digito1"] = (Convert.ToInt32(ViewState["Digito1"]) + 1).ToString();
                        Modulo11ASBACE(ViewState["CDAsBace"].ToString() + ViewState["Digito1"].ToString(), 7, false);
                    }
                    else
                        if (Convert.ToInt32(ViewState["Digito1"]) == 9)
                        {
                            ViewState["Digito1"] = "0";
                            Modulo11ASBACE(ViewState["CDAsBace"].ToString() + ViewState["Digito1"].ToString(), 7, false);
                        }
                }
                else
                    if (Rest > 1)
                        ViewState["Digito2"] = (11 - Rest).ToString();
        }

        #endregion

        #region Nosso Numero
        public string NossoNumero(string Numero)
        {
            int total = 9;

            //adiciona zeros. sem o digito calculado, deve ter 8 caracteres
            int total2 = 8;
            int tamanhoValor3 = Numero.ToString().Length;
            string valorConcat3 = Numero.ToString();
            for (int i = 0; i < (total2 - tamanhoValor3); i++)
            {
                valorConcat3 = "0" + valorConcat3;
            }
            Numero = valorConcat3;


            string NumNumero, Digito, NumFormato;
            NumNumero = "014" + Numero;
            Digito = Modulo11(NumNumero, 9, false);
            ViewState["NossoNumeros"] = Numero + Digito;
            //adiciona zeros. com o digito, deve ter 9 caracteres.
            int tamanhoValor = ViewState["NossoNumeros"].ToString().Length;
            string valorConcat = ViewState["NossoNumeros"].ToString();
            for (int i = 0; i < (total - tamanhoValor); i++)
            {
                valorConcat = "0" + valorConcat;
            }
            ViewState["NossoNumeros"] = valorConcat;
            //formata e adiciona os zeros
            NumFormato = Numero + "-" + Digito;
            //int tamanhoValor2 = NumFormato.ToString().Length;
            //string valorConcat2 = NumFormato.ToString();
            //for (int i = 0; i < (total - tamanhoValor); i++)
            //{
            //    valorConcat2 = "0" + valorConcat2;
            //}
            //NumFormato = valorConcat2;
            return NumFormato;
        }
        #endregion

        #region Add Zeros
        public string addZeros(double Valor)
        {
            int total = 10;
            Valor = Valor * 100;
            int tamanhoValor = Valor.ToString().Length;
            string valorConcat = Valor.ToString();

            for (int i = 0; i < (total - tamanhoValor); i++)
            {
                valorConcat = "0" + valorConcat;
            }
            return valorConcat;
        }
        #endregion

        #region Gera o Código de Barra(código)
        public string CodBarra(double Valor, DateTime Data_Venc)
        {

            string ValorDocumento, FatorVencimento, DigitoDAC;

            ValorDocumento = addZeros(Valor);
            FatorVencimento = CalculaFatorVencimento(Data_Venc);
            DigitoDAC = Modulo11Linha("0479" + FatorVencimento + ValorDocumento + ViewState["CDAsBace"].ToString(), 9, true);
            ViewState["CodFV"] = FatorVencimento + ValorDocumento;
            ViewState["Codigo"] = "0479" + ViewState["CDAsBace"].ToString() + DigitoDAC + ViewState["CodFV"].ToString();
            return "0479" + DigitoDAC + FatorVencimento + ValorDocumento + ViewState["CDAsBace"].ToString();
        }
        #endregion


        #region ASBACE
        public string ASBace()
        {
            string Agencia, Conta;
            Agencia = "14";
            Conta = "031264024";
            ViewState["Digito1"] = Modulo10(Agencia + Conta + ViewState["NossoNumeros"].ToString() + "047");
            ViewState["CDAsBace"] = Agencia + Conta + ViewState["NossoNumeros"].ToString() + "047";
            Modulo11ASBACE(Agencia + Conta + ViewState["NossoNumeros"].ToString() + "047" + ViewState["Digito1"].ToString(), 7, false);//  Digito2 := 
            ViewState["CDAsBace"] = Agencia + Conta + ViewState["NossoNumeros"].ToString() + "047" + ViewState["Digito1"].ToString() + ViewState["Digito2"].ToString();
            return Agencia + "." + Conta + "." + ViewState["NossoNumeros"].ToString() + "." + "047" + "/" + ViewState["Digito1"].ToString() + ViewState["Digito2"].ToString();
        }
        #endregion


        #region Linha Digitável
        public string LinhaDigitavel()
        {
            //A linha digitável é baseada na informações do código de barras.
            //As informações que fazem parte do código de barras são:
            //Posição         Conteúdo
            //1 a 3           Número do banco
            //4               Código da Moeda - 9 para Real
            //5               Digito verificador do Código de Barras
            //6 a 19          Valor (12 inteiros e 2 decimais)
            //20 a 44         Campo Livre definido por cada banco


            string p1, p2, p3, p4, p5, p6, Campo1, Campo2, Campo3, Campo4, Campo5;


            //Campo 1 - composto pelo código do banco, código da moeda, as cinco primeiras posições
            //do campo livre e DV (modulo10) desse campo

            //p1 = ViewState["Codigo"].ToString().Substring(1, 4);// (Codigo,1,4);
            p1 = ViewState["Codigo"].ToString().Substring(0, 4);// (Codigo,1,4);            
            //p2 = ViewState["Codigo"].ToString().Substring(5, 5);//Copy(Codigo,5,5);//20
            p2 = ViewState["Codigo"].ToString().Substring(4, 5);//Copy(Codigo,5,5);//20
            p3 = Modulo10(p1 + p2);
            p4 = p1 + p2 + p3;
            //p5 = p4.Substring(1, 5);
            p5 = p4.Substring(0, 5);
            //p6 = p4.Substring(6, 5);
            p6 = p4.Substring(5, 5);
            Campo1 = p5 + "." + p6;


            //Campo 2 - composto pelas posiçoes 6 a 15 do campo livre
            //e DV (modulo10) deste campo

            p1 = ViewState["Codigo"].ToString().Substring(9, 10);//Copy(Codigo,10,10);//25
            //p1 = ViewState["Codigo"].ToString().Substring(10, 10);//Copy(Codigo,10,10);//25
            p2 = Modulo10(p1);
            p3 = p1 + p2;
            //p4 = p3.Substring(1, 5);
            p4 = p3.Substring(0, 5);
            //p5 = p3.Substring(6, 6);
            p5 = p3.Substring(5, 6);
            Campo2 = p4 + "." + p5;

            //Campo 3 - composto pelas posicoes 16 a 25 do campo livre
            //e DV (modulo10) deste campo

            //p1 = ViewState["Codigo"].ToString().Substring(20, 10);//Copy(Codigo,20,10);
            p1 = ViewState["Codigo"].ToString().Substring(19, 10);//Copy(Codigo,20,10);
            p2 = Modulo10(p1);
            p3 = p1 + p2;
            //p4 = p3.Substring(1, 5);
            p4 = p3.Substring(0, 5);
            //p5 = p3.Substring(6, 6);
            p5 = p3.Substring(5, 6);

            Campo3 = p4 + "." + p5;


            //Campo 4 - digito verificador do codigo de barras

            //Campo4 = ViewState["Codigo"].ToString().Substring(30, 1); //Copy(Codigo,30,1);
            Campo4 = ViewState["Codigo"].ToString().Substring(29, 1); //Copy(Codigo,30,1);


            //   Campo 5 - composto pelo valor nominal do documento, sem indicacao
            //   de zeros a esquerda e sem edicao (sem ponto e virgula). Quando se
            //   tratar de valor zerado, a representacao deve ser 000 (tres zeros).

            Campo5 = ViewState["Codigo"].ToString().Substring(30, 14); //Copy(Codigo,31,14);
            //Campo5 = ViewState["Codigo"].ToString().Substring(31, 14); //Copy(Codigo,31,14);

            return Campo1 + " " + Campo2 + " " + Campo3 + " " + Campo4 + " " + Campo5;
        }
        #endregion

        #region  * Início do Método para gerar a imagem do CodBarras
        public Bitmap CodigoBarra(string Codigo)
        {
            Int16 Largura = 449;//55;
            Int16 Altura = 449;
            int posBar, barFina, barLarga, count;
            string strCodigo, strBC;
            string[] BarCodes = new string[100];
            Bitmap bmp;
            Graphics grf;

            if ((Convert.ToDouble(Codigo) - Convert.ToDouble(Convert.ToDouble(Codigo) / 2) * 2 + Convert.ToDouble(Math.Sign(Convert.ToDouble(Codigo)) != Math.Sign(2)) * 2) == 0)
            {
                strCodigo = Codigo;
            }
            else
            {
                strCodigo = "0" + Codigo;
            }

            BarCodes[0] = "00110";
            BarCodes[1] = "10001";
            BarCodes[2] = "01001";
            BarCodes[3] = "11000";
            BarCodes[4] = "00101";
            BarCodes[5] = "10100";
            BarCodes[6] = "01100";
            BarCodes[7] = "00011";
            BarCodes[8] = "10010";
            BarCodes[9] = "01010";

            for (int count1 = 9; count1 >= 0; count1--)
            {
                for (int count2 = 9; count2 >= 0; count2--)
                {
                    count = count1 * 10 + count2;
                    strBC = "";
                    for (int count3 = 1; count3 <= 5; count3++)
                    {
                        strBC += BarCodes[count1].Substring(count3 - 1, 1) + BarCodes[count2].Substring(count3 - 1, 1);
                    }
                    BarCodes[count] = strBC;
                }
            }

            bmp = new Bitmap(Largura, Altura);
            grf = Graphics.FromImage(bmp);
            grf.Clear(Color.White);

            barFina = 1;
            barLarga = 3;
            posBar = 0;

            // BEGIN - Inicio da Barra
            grf.FillRectangle(new SolidBrush(Color.Black), posBar, 0, barFina, Altura);
            posBar += barFina;

            grf.FillRectangle(new SolidBrush(Color.White), posBar, 0, barFina, Altura);
            posBar += barFina;

            grf.FillRectangle(new SolidBrush(Color.Black), posBar, 0, barFina, Altura);
            posBar += barFina;

            grf.FillRectangle(new SolidBrush(Color.White), posBar, 0, barFina, Altura);
            posBar += barFina;

            // END - Inicio da Barra
            // BEGIN - Dados do Código

            int i;

            while (strCodigo.Length > 0)
            {
                i = Convert.ToInt32(strCodigo.Substring(0, 2).ToString());
                strCodigo = strCodigo.Substring(2);
                strBC = BarCodes[i];
                for (int count1 = 1; count1 <= 10; count1 += 2)
                {
                    if (strBC.Substring(count1 - 1, 1) == "0")
                    {
                        grf.FillRectangle(new SolidBrush(Color.Black), posBar, 0, barFina, Altura);
                        posBar += barFina;
                    }
                    else
                    {
                        grf.FillRectangle(new SolidBrush(Color.Black), posBar, 0, barLarga, Altura);
                        posBar += barLarga;
                    }

                    if (strBC.Substring(count1, 1) == "0")
                    {
                        grf.FillRectangle(new SolidBrush(Color.White), posBar, 0, barFina, Altura);
                        posBar += barFina;
                    }
                    else
                    {
                        grf.FillRectangle(new SolidBrush(Color.White), posBar, 0, barLarga, Altura);
                        posBar += barLarga;
                    }
                }
            }
            // END - Dados do Código

            // BEGIN - Fim da Barra
            grf.FillRectangle(new SolidBrush(Color.Black), posBar, 0, barLarga, Altura);
            posBar += barLarga;

            grf.FillRectangle(new SolidBrush(Color.White), posBar, 0, barFina, Altura);
            posBar += barFina;

            grf.FillRectangle(new SolidBrush(Color.Black), posBar, 0, barFina, Altura);
            posBar += barFina;
            // END - Fim da Barra

            return bmp;
        }
        #endregion Fim do Método para gerar a imagem do CodBarras
    }
}